class BitUtility(object):
    @staticmethod
    def align_greater_equal(v: int, base: int) -> int:
        if v > base:
            return v if (v & (v-1) == 0) else (1 << v.bit_length())
        else:
            return base

    @staticmethod
    def is_two_power(v: int) -> bool:
        return v > 0 and  (v & (v -1) == 0) 

class Bit(object):
    MASK = 0xFFFFFFFFFFFFFFFF
    def __init__(self, bindex):
        self.__bindex = 63 if bindex >= 64 else bindex

    def bindex(self) -> int:
        return self.__bindex

    def value(self) -> int: 
        return 1 << self.__bindex

    def mask(self) -> int:
        return (1 << (self.__bindex + 1) ) - 1

    def clear(self, v: int) -> int:
        return v & (~(1 << self.__bindex) & Bit.MASK)
         
    def set(self, v: int) -> int:
        return v | (1 << self.__bindex)

    def is_set(self, v: int) -> bool:
        return ((1 << self.__bindex) & v) != 0

    def is_clear(self, v: int) -> bool:
        return ((1 << self.__bindex) & v) == 0


import unittest
class TestBitUtility(unittest.TestCase):
    def test_align_greater_equal(self):
        self.assertEqual(512, BitUtility.align_greater_equal(0, 512))
        self.assertEqual(512, BitUtility.align_greater_equal(1, 512))
        self.assertEqual(512, BitUtility.align_greater_equal(511, 512))
        self.assertEqual(512, BitUtility.align_greater_equal(512, 512))

        self.assertEqual(1024, BitUtility.align_greater_equal(513, 512))
        self.assertEqual(1024, BitUtility.align_greater_equal(1023, 512))
        self.assertEqual(1024, BitUtility.align_greater_equal(1024, 512))
        self.assertEqual(2048, BitUtility.align_greater_equal(1025, 512))


    def test_bit_ops(self):
        b0 = Bit(0)
        self.assertEqual(0x01, b0.value())
        self.assertEqual(0x01, b0.mask());

        v = b0.clear(0x01)
        self.assertEqual(0x00, v)
        v = b0.clear(0x00)
        self.assertEqual(0x00, v)

        v = b0.set(0x00)
        self.assertEqual(0x01, v)
        v = b0.set(0x01)
        self.assertEqual(0x01, v)

        self.assertTrue(b0.is_set(0x01))
        self.assertFalse(b0.is_set(0x00))

        self.assertTrue(b0.is_clear(0x00))
        self.assertFalse(b0.is_clear(0x01))


        b3 = Bit(3)
        self.assertEqual(0x08, b3.value());
        self.assertEqual(0x0F, b3.mask());

        v = b3.clear(0x1F)
        self.assertEqual(0x17, v)
        v = b3.clear(0x10)
        self.assertEqual(0x10, v)

        v = b3.set(0x00)
        self.assertEqual(0x08, v)
        v = b3.set(0x70)
        self.assertEqual(0x78, v)


        b7 = Bit(7)
        self.assertEqual(0x80, b7.value());
        self.assertEqual(0xFF, b7.mask());

        v = b7.clear(0xF3)
        self.assertEqual(0x73, v)
        v = b7.clear(0x7F)
        self.assertEqual(0x7F, v)

        v = b7.set(0x00)
        self.assertEqual(0x80, v)
        v = b7.set(0x80)
        self.assertEqual(0x80, v)


        b15 = Bit(15)
        self.assertEqual(0x8000, b15.value());
        self.assertEqual(0xFFFF, b15.mask());

        v = b15.clear(0x0FFFF)
        self.assertEqual(0x07FFF, v)
        v = b15.clear(0x00)
        self.assertEqual(0x00, v)

        v = b15.set(0x0000)
        self.assertEqual(0x8000, v)
        v = b15.set(0x8000)
        self.assertEqual(0x8000, v)

        b23 = Bit(23)
        self.assertEqual(0x800000, b23.value());
        self.assertEqual(0xFFFFFF, b23.mask());

        v = b23.clear(0xFFFFFF)
        self.assertEqual(0x7FFFFF, v)
        v = b23.clear(0x7FFFFF)
        self.assertEqual(0x7FFFFF, v)

        v = b23.set(0x000000)
        self.assertEqual(0x800000, v)
        v = b23.set(0x800000)
        self.assertEqual(0x800000, v)
